//************************************************************************
//Developed by Guo Ming Li 2009/2010
//Source code:
//  The source code may be freely modified or used but this credit section may not be removed 
//  The original author must be notified of any modifications plus a copy of 
//  the changed source code
//Contact info: mailto://gming.li@gmail.com
//************************************************************************
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.BizTalk.ExplorerOM;
using Microsoft.BizTalk.ApplicationDeployment;


namespace GML.BizTalk.OperationManager.Library
{
    public class Applications
    {
        public static bool Restart(string appName, string serverName, string btsMgmtDB)
        {
            return Exec(ApplicationAction.RESTART, appName, serverName, btsMgmtDB);
        }

        public static bool Start(string appName, string serverName, string btsMgmtDB)
        {
            return Exec(ApplicationAction.START, appName, serverName, btsMgmtDB);
        }

        public static bool Stop(string appName, string serverName, string btsMgmtDB)
        {
            return Exec(ApplicationAction.STOP, appName, serverName, btsMgmtDB);
        }

        private const string DEFAULT_SERVER = ".";
        private const string DEFAULT_MGTDB = "BizTalkMgmtDb";
        public static bool Exec(ApplicationAction Action, string appName, string serverName, string btsMgmtDB)
        {
            // Create the root object and set the connection string
            BtsCatalogExplorer catalog = new BtsCatalogExplorer();
            Microsoft.BizTalk.ExplorerOM.Application app = null;

            try
            {
                catalog.ConnectionString = "SERVER=" + (string.IsNullOrEmpty(serverName) ? DEFAULT_SERVER : serverName) + ";" +
                                                         "DATABASE=" + (string.IsNullOrEmpty(btsMgmtDB) ? DEFAULT_MGTDB : btsMgmtDB) + ";" +
                                                         "Integrated Security=SSPI";

                //string applicationName = args[1];
                app = catalog.Applications[appName];
                if (null == app)
                {
                    Console.WriteLine("Application " + appName + " does not exist.");
                    Logger.doLog(Guid.NewGuid().ToString(), "Application " + appName + " does not exist.", Logger.ServerityLevel.INFO);
                    return false;
                }

                if (Action.Equals(ApplicationAction.START))
                {
                    app.Start(Microsoft.BizTalk.ExplorerOM.ApplicationStartOption.StartAll);
                }
                else if (Action.Equals(ApplicationAction.STOP))
                {
                    app.Stop(Microsoft.BizTalk.ExplorerOM.ApplicationStopOption.StopAll);
                }
                else if (Action.Equals(ApplicationAction.RESTART))
                {
                    app.Stop(Microsoft.BizTalk.ExplorerOM.ApplicationStopOption.StopAll);
                    app.Start(Microsoft.BizTalk.ExplorerOM.ApplicationStartOption.StartAll);
                }
                else
                {
                    Console.WriteLine("Unknown action " + Action.ToString() + ".");
                    Logger.doLog(Guid.NewGuid().ToString(), "Unknown action " + Action.ToString() + ".", Logger.ServerityLevel.INFO);
                    return false;
                }
                catalog.SaveChanges();
                return true;

            }
            catch (Exception ex)
            {
                catalog.DiscardChanges();
                throw ex;
            }
            finally
            {
                //if (catalog != null) catalog.Dispose();
                catalog = null;
                app = null;
            }
        }

        public enum ApplicationAction
        {
            START,
            STOP,
            RESTART
        }

        public static bool Import(string sMsiPackagePath, string sAppName, bool isOverwrite, string sEnvID,string btsDbServerName, string btsMgntDbName)
        {
            try
            {
                //this.Validate();
                string msiPath = sMsiPackagePath; // base.Args["Package"];
                string title = sAppName; // base.Args["ApplicationName"];
                bool overwrite = isOverwrite; // CommandLineHelper.ArgSpecified(base.Args, "Overwrite");
                string str3 = btsDbServerName; // base.Args["Server"];
                string str4 = btsMgntDbName; // base.Args["Database"];
                string str5 = sEnvID; // base.Args["Environment"];
                //string text1 = base.Args["EnvironmentFolder"];
                //string formattedString = CommandResources.GetFormattedString(CommandResources.ResourceID.ImportApplication, new object[] { msiPath, title, str3, str4 });
                //base.WriteLogEntry(LogEntryType.Information, formattedString);
                ICollection<string> applicationReferences = null;
                IInstallPackage package = DeploymentUnit.ScanPackage(msiPath);
                applicationReferences = package.References;
                if ((title == null) || (title.Length == 0))
                {
                    title = package.Title;
                }
                Group group = new Group();
                try
                {
                    group.DBServer = str3;
                    group.DBName = str4;
                    Microsoft.BizTalk.ApplicationDeployment.Application application = (Microsoft.BizTalk.ApplicationDeployment.Application)group.CreateInstance(typeof(Microsoft.BizTalk.ApplicationDeployment.Application));
                    application.Name = title;
                    application.UILevel = 2;
                    //application.Log += new LogEventHandler(this.OnLog);
                    IDictionary<string, object> requestProperties = null;
                    requestProperties = new Dictionary<string, object>();
                    if ((str5 != null) && (str5.Trim().Length > 0))
                    {
                        requestProperties.Add("TargetEnvironment", str5);
                    }
                    application.Import(msiPath, requestProperties, applicationReferences, overwrite);
                    return true;
                }
                catch (Exception exception)
                {
                    //Trace.WriteLine(exception.ToString(), new object[0]);
                    //System.Diagnostics.Debug.WriteLine(exception.ToString());
                    System.Diagnostics.Debug.WriteLine(exception.Message + Environment.NewLine + exception.StackTrace);
                    Logger.doLog(Guid.NewGuid().ToString(), exception.Message, Logger.ServerityLevel.ERROR);
                    Logger.doLog(Guid.NewGuid().ToString(), exception.StackTrace, Logger.ServerityLevel.ERROR);
                    group.Abort();
                    throw exception;
                }
                finally
                {
                    if (group != null)
                    {
                        group.Dispose();
                    }
                }
            }
            catch (Exception exception2)
            {
                System.Diagnostics.Debug.WriteLine(exception2.Message + Environment.NewLine + exception2.StackTrace);
                Logger.doLog(Guid.NewGuid().ToString(), exception2.Message, Logger.ServerityLevel.ERROR);
                Logger.doLog(Guid.NewGuid().ToString(), exception2.StackTrace, Logger.ServerityLevel.ERROR);
                //base.ShowError(exception2);
                //base.commandResult = new CommandResult(exception2);
                if (((exception2 is OutOfMemoryException) || (exception2 is ExecutionEngineException)) || (exception2 is StackOverflowException))
                {
                    throw exception2;
                }
            }
            return true;
        }

        public static List<string> GetAssemblies(string btsDbServerName, string btsMgntDbName, string sAppName)
        {
            Microsoft.BizTalk.ExplorerOM.Application app = null;
            List<string> result = new List<string>();
            try
            {
                app = GetApplication(sAppName, btsDbServerName, btsMgntDbName);
                foreach (BtsAssembly assembly in app.Assemblies)
                {
                    System.Diagnostics.Debug.WriteLine(
                       "assembly.Application.Name = " + assembly.Application.Name + Environment.NewLine +
                       "assembly.Culture = " + assembly.Culture + Environment.NewLine +
                       "assembly.DisplayName = " + assembly.DisplayName + Environment.NewLine +
                       "assembly.IsSystem.ToString() = " + assembly.IsSystem.ToString() + Environment.NewLine +
                       "assembly.PublicKeyToken = " + assembly.PublicKeyToken + Environment.NewLine +
                       "assembly.Version = " + assembly.Version + Environment.NewLine +
                       "");
                    Logger.doLog(Guid.NewGuid().ToString(), "assembly.Application.Name = " + assembly.Application.Name + Environment.NewLine +
                       "assembly.Culture = " + assembly.Culture + Environment.NewLine +
                       "assembly.DisplayName = " + assembly.DisplayName + Environment.NewLine +
                       "assembly.IsSystem.ToString() = " + assembly.IsSystem.ToString() + Environment.NewLine +
                       "assembly.PublicKeyToken = " + assembly.PublicKeyToken + Environment.NewLine +
                       "assembly.Version = " + assembly.Version + Environment.NewLine +
                       "", Logger.ServerityLevel.INFO);
                    result.Add(assembly.DisplayName);
                }
                return result;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
                Logger.doLog(Guid.NewGuid().ToString(), ex.Message, Logger.ServerityLevel.ERROR);
                Logger.doLog(Guid.NewGuid().ToString(), ex.StackTrace, Logger.ServerityLevel.ERROR);
                throw ex;
            }
            finally
            {
                app = null;
                result = null;
            }
        }
        public static PolicyCollection GetPolicyCollection(string btsAppName, string btsDbServerName, string btsMgntDbName)
        {
            Microsoft.BizTalk.ExplorerOM.Application application = null;
            PolicyCollection policies = null;
            try
            {
                application = GetApplication(btsAppName, btsDbServerName, btsMgntDbName);
                policies = application.Policies;
                return policies;
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                Logger.doLog(Guid.NewGuid().ToString(), e.Message, Logger.ServerityLevel.ERROR);
                Logger.doLog(Guid.NewGuid().ToString(), e.StackTrace, Logger.ServerityLevel.ERROR);
                throw e;
            }
            finally
            {
                application = null;
                policies = null;
            }

        }

        public static Microsoft.BizTalk.ExplorerOM.Application GetApplication(string btsAppName, string btsDbServerName, string btsMgntDbName)
        {
            BtsCatalogExplorer catalog = new BtsCatalogExplorer();
            Microsoft.BizTalk.ExplorerOM.ApplicationCollection applications = null;
            try
            {
                catalog.ConnectionString = Helper.GetConnectionString(btsDbServerName, btsMgntDbName);
                applications = catalog.Applications;
                foreach (Microsoft.BizTalk.ExplorerOM.Application application in applications)
                {
                    System.Diagnostics.Debug.WriteLine(
                       "application.Name = " + application.Name + Environment.NewLine +
                       "");
                    Logger.doLog(Guid.NewGuid().ToString(), "application.Name = " + application.Name, Logger.ServerityLevel.INFO);
                    if (application.Name.Equals(btsAppName))
                    {
                        return application;
                    }
                }
                return null;
            }
            catch (Exception e)
            {
                catalog.DiscardChanges();
                System.Diagnostics.Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                Logger.doLog(Guid.NewGuid().ToString(), e.Message, Logger.ServerityLevel.ERROR);
                Logger.doLog(Guid.NewGuid().ToString(), e.StackTrace, Logger.ServerityLevel.ERROR);
                throw e;
            }
            finally
            {
                //if (catalog != null) catalog.Dispose();
                catalog = null;
                applications = null;
            }

        }

        public static List<string> GetListOfApplicationNames(string btsDbServerName, string btsMgntDbName, bool blnListSystem)
        {
            BtsCatalogExplorer catalog = new BtsCatalogExplorer();
            Microsoft.BizTalk.ExplorerOM.ApplicationCollection applications = null;
            List<string> appNames = new List<string>();
            try
            {
                //////////////////////////////////////////////////////
                List<string> spnames = new List<string>();
                spnames.Add("SP_bank1");
                spnames.Add("SP_bank2");
                SendPortCollection spc = SendPorts.GetSendPorts(spnames, btsDbServerName, btsMgntDbName);
                if (spc != null)
                {
                    System.Diagnostics.Debug.WriteLine("spc is NOT null");
                    foreach (SendPort sp in spc)
                    {
                        System.Diagnostics.Debug.WriteLine(sp.Name);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("spc is null");
                }

                //////////////////////////////////////
                List<ReceivePort> receivePorts = ReceivePorts.GetReceivePorts(btsDbServerName, btsMgntDbName, "AirelBPM.WorkFlow");
                catalog.ConnectionString = Helper.GetConnectionString(btsDbServerName, btsMgntDbName);
                applications = catalog.Applications;
                foreach (Microsoft.BizTalk.ExplorerOM.Application application in applications)
                {
                    if (application.IsSystem && !blnListSystem)
                    {
                        //do not list
                    }
                    else
                    {
                        appNames.Add(application.Name);
                    }
                }
                return appNames;
            }
            catch (Exception e)
            {
                catalog.DiscardChanges();
                System.Diagnostics.Debug.WriteLine(e.Message + Environment.NewLine + e.StackTrace);
                Logger.doLog(Guid.NewGuid().ToString(), e.Message, Logger.ServerityLevel.ERROR);
                Logger.doLog(Guid.NewGuid().ToString(), e.StackTrace, Logger.ServerityLevel.ERROR);
                throw e;
            }
            finally
            {
                //if (catalog != null) catalog.Dispose();
                catalog = null;
                applications = null;
                appNames = null;
            }
        }

        public static List<string> GetMessageTypes(string btsDbServerName, string btsMgntDbName, string sAppName)
        {
            Microsoft.BizTalk.ExplorerOM.Application app = null;
            List<string> result = new List<string>();
            try
            {
                app = GetApplication(sAppName, btsDbServerName, btsMgntDbName);
                foreach (Schema schema in app.Schemas)
                {
                    //System.Diagnostics.Debug.WriteLine(
                    //   "schema.BtsAssembly.Name = " + schema.BtsAssembly.Name + Environment.NewLine +
                    //   "schema.Description = " + schema.Description + Environment.NewLine +
                    //   "schema.FullName = " + schema.FullName + Environment.NewLine +
                    //   "schema.Properties = " + schema.Properties.ToString() + Environment.NewLine +
                    //   "schema.RootName = " + schema.RootName + Environment.NewLine +
                    //   "schema.TargetNameSpace = " + schema.TargetNameSpace + Environment.NewLine +
                    //   "schema.TrackedPropertyNames = " + schema.TrackedPropertyNames.ToString() + Environment.NewLine +
                    //   "schema.Description = " + schema.Type.ToString() + Environment.NewLine +
                    //   "schema.XmlContent = " + schema.XmlContent + Environment.NewLine +
                    //   "");

                    //Logger.doLog(Guid.NewGuid().ToString(),
                    //   "schema.BtsAssembly.Name = " + schema.BtsAssembly.Name + Environment.NewLine +
                    //   "schema.Description = " + schema.Description + Environment.NewLine +
                    //   "schema.FullName = " + schema.FullName + Environment.NewLine +
                    //   "schema.Properties = " + schema.Properties.ToString() + Environment.NewLine +
                    //   "schema.RootName = " + schema.RootName + Environment.NewLine +
                    //   "schema.TargetNameSpace = " + schema.TargetNameSpace + Environment.NewLine +
                    //   "schema.TrackedPropertyNames = " + schema.TrackedPropertyNames.ToString() + Environment.NewLine +
                    //   "schema.Description = " + schema.Type.ToString() + Environment.NewLine +
                    //   "schema.XmlContent = " + schema.XmlContent + Environment.NewLine +
                    //   "", Logger.ServerityLevel.INFO);
                    result.Add(schema.TargetNameSpace + "#" + schema.RootName);
                }
                return result;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
                Logger.doLog(Guid.NewGuid().ToString(), ex.Message, Logger.ServerityLevel.ERROR);
                Logger.doLog(Guid.NewGuid().ToString(), ex.StackTrace, Logger.ServerityLevel.ERROR);
                throw ex;
            }
            finally
            {
                result = null;
                app = null;
            }
        }
    }
}